import json
import uuid
from typing import Dict, List, Optional, Any, Tuple
from sqlalchemy.ext.asyncio import AsyncSession
from datetime import datetime
from loguru import logger

from app.ai.intent_recognition_engine import IntentRecognitionEngine
from app.ai.task_execution_engine import TaskExecutionEngine
from app.models.db import UserSession, UserMsg


class IntelligentAssistantEngine:
    """智能助手引擎 - 高校教务系统的核心智能引擎"""
    
    def __init__(self):
        self.intent_engine = IntentRecognitionEngine()
        self.task_engine = TaskExecutionEngine()
        
    async def process_user_input_with_existing_message(
        self, 
        user_input: str, 
        session_id: str, 
        user_id: str, 
        user_message_id: str,
        db: AsyncSession
    ) -> Dict[str, Any]:
        """
        处理用户输入的完整流程，但不保存用户消息（用于已经保存过用户消息的场景）
        
        Args:
            user_input: 用户输入内容
            session_id: 会话ID
            user_id: 用户ID
            user_message_id: 已存在的用户消息ID
            db: 数据库会话
            
        Returns:
            Dict[str, Any]: 处理结果
        """
        try:
            
            # 1. 多意图识别（不保存用户消息）
            intent_results = await self.intent_engine.recognize_intent_without_saving(
                user_input, session_id, user_id, db
            )
            
         
            # 2. 处理多意图执行
            result = await self._process_multiple_intents(
                intent_results, session_id, user_id, db
            )
            
            return result
            
        except Exception as e:
            logger.error(f"处理用户输入失败: {str(e)}")
            return {
                "status": "error",
                "message": "智能助手处理失败，请稍后重试",
                "error": str(e)
            }
    
    async def _process_multiple_intents(
        self, 
        intent_results: List[Dict[str, Any]], 
        session_id: str, 
        user_id: str, 
        db: AsyncSession
    ) -> Dict[str, Any]:
        """
        处理意图识别结果（统一处理单个或多个意图）
        
        Args:
            intent_results: 意图识别结果列表
            session_id: 会话ID
            user_id: 用户ID
            db: 数据库会话
            
        Returns:
            处理结果
        """
        try:
            if not intent_results:
                return {
                    "status": "error",
                    "message": "未识别到任何有效意图"
                }
            
            logger.info(f"处理{len(intent_results)}个意图")
            
            # 按next_action分类所有意图
            need_params_intents = [
                intent for intent in intent_results 
                if intent.get("next_action") == "ask_params"
            ]
            
            confirm_intents = [
                intent for intent in intent_results 
                if intent.get("next_action") == "confirm"
            ]
            
            executable_intents = [
                intent for intent in intent_results 
                if intent.get("next_action") == "execute"
            ]
            
            unknown_intents = [
                intent for intent in intent_results 
                if intent.get("next_action") not in ["ask_params", "confirm", "execute"]
            ]
            
            # 优先级处理：参数请求 > 确认请求 > 执行 > 未知
            if need_params_intents:
                return await self._handle_param_requests(
                    need_params_intents, session_id, user_id, db
                )
            
            if confirm_intents:
                return await self._handle_confirmations(
                    confirm_intents, session_id, user_id, db
                )
            
            if executable_intents:
                # 统一任务执行 - 不区分单个还是多个
                return await self._execute_intents(
                    executable_intents, session_id, user_id, db
                )
            
            # 处理未知意图
            if unknown_intents:
                return await self._handle_unknown_intents(
                    unknown_intents, session_id, user_id, db
                )
            
            # 兜底处理
            return {
                "status": "error",
                "message": "无法处理的意图类型"
            }
            
        except Exception as e:
            logger.error(f"处理意图失败: {str(e)}")
            return {
                "status": "error",
                "message": "意图处理失败",
                "error": str(e)
            }
    
    async def _handle_param_requests(
        self, 
        intents: List[Dict[str, Any]], 
        session_id: str, 
        user_id: str, 
        db: AsyncSession
    ) -> Dict[str, Any]:
        """处理参数请求 - 直接使用AI生成的消息"""
        try:
            # 🎯 提取查询类型信息
            query_style = None
            response_style = None
            for intent in intents:
                if intent.get("intent_type") == "data_query":
                    query_style = intent.get("query_style")
                    response_style = intent.get("response_style")
                    break
            
            # 根据意图数量决定上下文格式
            if len(intents) == 1:
                intent = intents[0]
                message = intent.get("user_message", "请提供更多信息以便我帮助您完成操作。")
                context = intent.copy()  # 使用 copy 避免修改原始对象
                response_type = "parameter_request"
            else:
                # 获取第一个有消息的意图，或使用合并消息
                message = None
                for intent in intents:
                    if intent.get("user_message"):
                        message = intent.get("user_message")
                        break
                
                if not message:
                    message = f"请为这{len(intents)}个操作提供必要的参数信息。"
                
                context = {
                    "multiple_intents": [
                        {
                            "intent_id": intent.get("intent_id"),
                            "intent_type": intent.get("intent_type"),
                            "task_name": intent.get("task_name"),
                            "missing_params": intent.get("missing_params", [])
                        } for intent in intents
                    ],
                    "total_intents": len(intents)
                }
                response_type = "multiple_parameter_request"
            
            # 🎯 添加查询类型信息到上下文
            if query_style:
                context["query_style"] = query_style
            if response_style:
                context["response_style"] = response_style
            
            # 保存助手回复
            await self._save_assistant_message(message, session_id, user_id, context, db)
            
            return {
                "status": "need_more_info",
                "message": message,
                "intent_context": context,
                "response_type": response_type
            }
                
        except Exception as e:
            logger.error(f"处理参数请求失败: {str(e)}")
            return {
                "status": "error",
                "message": "参数处理失败"
            }
    
    async def _handle_confirmations(
        self, 
        intents: List[Dict[str, Any]], 
        session_id: str, 
        user_id: str, 
        db: AsyncSession
    ) -> Dict[str, Any]:
        """处理确认请求 - 直接使用AI生成的消息"""
        try:
            # 🎯 提取查询类型信息
            query_style = None
            response_style = None
            for intent in intents:
                if intent.get("intent_type") == "data_query":
                    query_style = intent.get("query_style")
                    response_style = intent.get("response_style")
                    break
            
            # 根据意图数量决定上下文格式
            if len(intents) == 1:
                intent = intents[0]
                message = intent.get("user_message", "⚠️ 此操作可能存在风险，请确认是否继续执行？\n\n请回复'确认'或'取消'。")
                context = intent.copy()  # 使用 copy 避免修改原始对象
                response_type = "confirmation_request"
            else:
                # 获取第一个有消息的意图，或使用默认消息
                message = None
                for intent in intents:
                    if intent.get("user_message"):
                        message = intent.get("user_message")
                        break
                
                if not message:
                    message = f"⚠️ 您即将执行{len(intents)}个操作，请确认是否继续？\n\n请回复'确认'或'取消'。"
                
                context = {
                    "multiple_intents": [
                        {
                            "intent_id": intent.get("intent_id"),
                            "intent_type": intent.get("intent_type"),
                            "task_name": intent.get("task_name")
                        } for intent in intents
                    ],
                    "total_intents": len(intents)
                }
                response_type = "multiple_confirmation_request"
            
            # 🎯 添加查询类型信息到上下文
            if query_style:
                context["query_style"] = query_style
            if response_style:
                context["response_style"] = response_style
            
            # 保存助手回复
            await self._save_assistant_message(message, session_id, user_id, context, db)
            
            return {
                "status": "need_confirmation",
                "message": message,
                "intent_context": context,
                "response_type": response_type
            }
                
        except Exception as e:
            logger.error(f"处理确认请求失败: {str(e)}")
            return {
                "status": "error",
                "message": "确认处理失败"
            }
    
    async def _handle_unknown_intents(
        self, 
        intents: List[Dict[str, Any]], 
        session_id: str, 
        user_id: str, 
        db: AsyncSession
    ) -> Dict[str, Any]:
        """处理未知意图 - 直接使用AI生成的消息"""
        try:
            avg_confidence = sum(intent.get("confidence", 0) for intent in intents) / len(intents)
            
            # 🎯 提取查询类型信息
            query_style = None
            response_style = None
            for intent in intents:
                if intent.get("intent_type") == "data_query":
                    query_style = intent.get("query_style")
                    response_style = intent.get("response_style")
                    break
            
            # 根据意图数量决定上下文格式
            if len(intents) == 1:
                intent = intents[0]
                confidence = intent.get("confidence", 0)
                message = intent.get("user_message")
                
                if not message:
                    # 兜底消息
                    if confidence < 0.5:
                        message = """抱歉，我没有完全理解您的需求。我可以帮您：

📋 **功能调用**
📊 **数据查询分析**
📈 **图表生成**
📄 **报告生成**

请详细描述您想要执行的操作，我会尽力帮助您。"""
                    else:
                        analysis_reason = intent.get('analysis_reason', '执行某项操作')
                        message = f"我理解您可能想要{analysis_reason}，但需要更多信息才能帮您完成。请详细说明您的需求。"
                
                context = intent.copy()  # 使用 copy 避免修改原始对象
                response_type = "clarification_request"
            else:
                # 获取第一个有消息的意图，或使用默认消息
                message = None
                for intent in intents:
                    if intent.get("user_message"):
                        message = intent.get("user_message")
                        break
                
                if not message:
                    message = f"抱歉，我没有完全理解您的{len(intents)}个需求。请详细描述您想要执行的操作，我会尽力帮助您。\n\n"
                    message += "您可以尝试：数据查询、图表生成、报告制作、系统操作等。"
                
                context = {
                    "multiple_intents": [
                        {
                            "intent_id": intent.get("intent_id"),
                            "intent_type": intent.get("intent_type"),
                            "confidence": intent.get("confidence", 0),
                            "analysis_reason": intent.get("analysis_reason", "需要更多信息")
                        } for intent in intents
                    ],
                    "total_intents": len(intents),
                    "avg_confidence": avg_confidence
                }
                response_type = "multiple_clarification_request"
            
            # 🎯 添加查询类型信息到上下文
            if query_style:
                context["query_style"] = query_style
            if response_style:
                context["response_style"] = response_style
            
            # 保存助手回复
            await self._save_assistant_message(message, session_id, user_id, context, db)
            
            return {
                "status": "need_clarification",
                "message": message,
                "confidence": avg_confidence,
                "intent_context": context,
                "response_type": response_type
            }
                
        except Exception as e:
            logger.error(f"处理未知意图失败: {str(e)}")
            return {
                "status": "error",
                "message": "意图处理失败"
            }
    

    
    async def _save_assistant_message(
        self, 
        message: str, 
        session_id: str, 
        user_id: str, 
        context: Dict[str, Any], 
        db: AsyncSession
    ):
        """保存助手回复消息"""
        try:
            assistant_msg = UserMsg(
                id=str(uuid.uuid4()),
                user_id=user_id,
                session_id=session_id,
                message=message,
                message_type="system",
                message_intent=context.get("intent_type", "unknown"),
                message_confirm=json.dumps(context, ensure_ascii=False),
                timestamp=datetime.now()
            )
            
            db.add(assistant_msg)
            await db.commit()
            
        except Exception as e:
            logger.error(f"保存助手消息失败: {str(e)}")
            await db.rollback()
    
    async def create_new_session(
        self, 
        user_id: str, 
        session_title: str, 
        db: AsyncSession
    ) -> str:
        """创建新的会话"""
        try:
            session_id = str(uuid.uuid4())
            
            new_session = UserSession(
                id=session_id,
                user_id=user_id,
                session_title=session_title or "智能助手对话",
                file_name="",
                file_url="",
                analysis_status="active",
                upload_time=datetime.now()
            )
            
            db.add(new_session)
            await db.commit()
            
            return session_id
            
        except Exception as e:
            logger.error(f"创建会话失败: {str(e)}")
            await db.rollback()
            raise e

    async def _execute_intents(
        self, 
        intents: List[Dict[str, Any]], 
        session_id: str, 
        user_id: str, 
        db: AsyncSession
    ) -> Dict[str, Any]:
        """
        执行意图任务 - 统一处理单个或多个任务
        
        Args:
            intents: 意图列表
            session_id: 会话ID
            user_id: 用户ID
            db: 数据库会话
            
        Returns:
            执行结果
        """
        try:
            logger.info(f"开始执行{len(intents)}个意图任务")
            
            # 统一使用多任务执行逻辑处理所有情况
            return await self.execute_tasks(
                intents, session_id, user_id, db
            )
                
        except Exception as e:
            logger.error(f"执行意图任务失败: {str(e)}")
            return {
                "status": "error",
                "message": f"任务执行失败: {str(e)}",
                "response_type": "error"
            }

    async def _format_execution_results(
        self, 
        execution_results: List[Dict[str, Any]], 
        success_count: int, 
        total_count: int
    ) -> Dict[str, Any]:
        """统一格式化执行结果"""
        try:
            # 确定整体状态
            if success_count == total_count:
                status = "success"
                if total_count == 1:
                    message = "✅ 任务执行成功"
                else:
                    message = f"✅ 所有{total_count}个任务都已成功完成！"
            elif success_count > 0:
                status = "partial_success"
                message = f"⚠️ {total_count}个任务中有{success_count}个成功完成，{total_count - success_count}个失败"
            else:
                status = "error"
                if total_count == 1:
                    message = "❌ 任务执行失败"
                else:
                    message = f"❌ 所有{total_count}个任务都执行失败"
            
            # 构建详细结果
            detailed_results = []
            
            for result in execution_results:
                # 检测数据结构类型并统一处理
                # 单任务情况：result["result"] 包含执行结果
                # 多任务情况：result 直接是执行结果
                if "result" in result and isinstance(result["result"], dict) and "task_type" in result.get("result", {}):
                    # 单任务格式：有嵌套的result字段
                    execution_result = result["result"]
                    intent_id = result.get("intent_id", "unknown")
                    intent_type = result.get("intent_type", "unknown")
                    task_name = result.get("task_name", "未知任务")
                    task_status = result.get("status", "unknown")
                else:
                    # 多任务格式：扁平结构
                    execution_result = result
                    intent_id = result.get("intent_id", "unknown")
                    intent_type = result.get("intent_type", "unknown") 
                    task_name = result.get("task_name", "未知任务")
                    task_status = result.get("status", "unknown")
                
                if task_status == "success":
                    task_type = execution_result.get("task_type")
                    
                    # 根据任务类型确定消息和数据
                    if task_type == "api_function":
                        task_message = f"✅ 已成功执行{execution_result.get('function_name')}功能"
                        task_data = execution_result.get("result")
                        response_type = "api_result"
                    elif task_type == "data_query":
                        total_rows = execution_result.get("total_rows", 0)
                        task_message = f"✅ {task_name}查询完成，共找到{total_rows}条数据"
                        task_data = {
                            "dataset_name": execution_result.get("dataset_name"),
                            "total_rows": total_rows,
                            "columns": execution_result.get("columns", []),
                            "data": execution_result.get("data", []),
                        }
                        response_type = "query_result"
                    elif task_type == "knowledge_query":
                        task_message = f"✅ {task_name}完成"
                        task_data = {
                            "query_text": execution_result.get("query_text"),
                            "answer": execution_result.get("answer"),
                            "sources": execution_result.get("sources", []),
                            "confidence": execution_result.get("confidence", 0.0),
                            "knowledge_category": execution_result.get("knowledge_category")
                        }
                        response_type = "knowledge_result"
                    else:
                        task_message = f"✅ {task_name}执行成功"
                        task_data = execution_result.get("result")
                        response_type = "task_result"
                    
                    detailed_results.append({
                        "intent_id": intent_id,
                        "intent_type": intent_type,
                        "task_name": task_name,
                        "status": "success",
                        "message": task_message,
                        "data": task_data
                    })
                
                elif task_status == "need_params":
                    task_message = execution_result.get("message", "需要更多参数信息")
                    detailed_results.append({
                        "intent_id": intent_id,
                        "intent_type": intent_type,
                        "task_name": task_name,
                        "status": "need_params",
                        "message": task_message,
                        "missing_params": execution_result.get("missing_params", []),
                        "ask_questions": execution_result.get("ask_questions", [])
                    })
                
                else:
                    error_msg = execution_result.get("message", "未知错误")
                    task_message = f"❌ {task_name}执行失败: {error_msg}"
                    
                    detailed_results.append({
                        "intent_id": intent_id,
                        "intent_type": intent_type,
                        "task_name": task_name,
                        "status": "error",
                        "message": task_message,
                        "error": error_msg
                    })
            
            # 🎯 提取意图上下文信息（query_style 和 response_style）
            intent_context = {}
            
            # 从成功的执行结果中提取 query_style 和 response_style
            for result in execution_results:
                execution_result = result.get("result", result) if "result" in result else result
                
                if result.get("status") == "success" and execution_result.get("task_type") == "data_query":
                    query_style = execution_result.get("query_style")
                    response_style = execution_result.get("response_style")
                    
                    if query_style:
                        intent_context["query_style"] = query_style
                    if response_style:
                        intent_context["response_style"] = response_style
                    break  # 只需要获取第一个数据查询的信息
            
            # 构建返回结果
            result_data = {
                "status": status,
                "message": message,
                "summary": {
                    "total_tasks": total_count,
                    "success_count": success_count,
                    "failed_count": total_count - success_count
                },
                "results": detailed_results,
                "response_type": "execution_result",
                "intent_context": intent_context  # 🎯 添加意图上下文
            }
            
            return result_data
                
        except Exception as e:
            logger.error(f"格式化执行结果失败: {str(e)}")
            logger.exception(e)
            return {
                "status": "error",
                "message": f"结果格式化失败: {str(e)}",
                "response_type": "error"
            }

    async def execute_tasks(
        self, 
        intent_results: List[Dict[str, Any]], 
        session_id: str, 
        user_id: str, 
        db: AsyncSession
    ) -> Dict[str, Any]:
        """
        执行多个任务
        
        参数:
            intent_results: 意图识别结果列表
            session_id: 会话ID
            user_id: 用户ID
            db: 数据库会话
            
        返回:
            执行结果汇总
        """
        execution_results = []
        
        try:
            # 1. 执行所有任务
            for intent_result in intent_results:
                logger.info(f"开始执行任务: {intent_result.get('task_name', 'unknown')}")
                 
                result = await self.task_engine.execute_task(
                    intent_result, session_id, user_id, db
                )
                
                # 添加任务名称到结果中
                result["task_name"] = intent_result.get("task_name", "未知任务")
                result["intent_type"] = intent_result.get("intent_type", "unknown")
                result["intent_id"] = intent_result.get("intent_id", "unknown")

                execution_results.append(result)
                
                logger.info(f"任务执行完成: {result.get('task_name')} - {result.get('status')}")
            
            # 2. 统计执行结果
            total_count = len(execution_results)
            success_count = sum(1 for r in execution_results if r.get("status") == "success")
            failed_count = total_count - success_count
            
            # 4. 返回格式化的执行结果
            return await self._format_execution_results(
                execution_results, success_count, total_count
            )
            
        except Exception as e:
            logger.error(f"执行任务集合失败: {str(e)}")
            logger.exception(e)
            
         
            
            return {
                "status": "error",
                "message": f"任务集合执行失败: {str(e)}",
                "execution_results": execution_results
            }